package com.example.demo.business.service;

import com.example.demo.base.bean.Meta;
import com.example.demo.base.exceptions.BaseException;
import com.example.demo.base.util.CommonUtil;
import com.example.demo.base.util.FileUtil;
import com.example.demo.business.bean.dto.CollectionDto;
import com.example.demo.business.bean.entity.*;
import com.example.demo.business.bean.vo.*;
import com.example.demo.business.dao.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
public class UserService {
    @Autowired
    private HUserDao hUserDao;
    @Autowired
    private HStarDao hStarDao;
    @Autowired
    private HVideoDao hVideoDao;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private HCollectionDao hCollectionDao;
    @Autowired
    private HMashDao hMashDao;
    @Autowired
    private HFeedBackDao hFeedBackDao;

    @Value("${upload.img.path}")
    private String imgPath;
    @Value("${web.img.path}")
    private String webPath;
    @Value("${web.promote.path}")
    private String promoteLinkPath;

    public Object register(String deviceToken,String source,String promeCode){

        HUser hUser = hUserDao.findByDevToken(deviceToken);

        if (hUser!=null){
            hUser.setAccessToken(UUID.randomUUID().toString());
        }else {
            hUser = new HUser();
            hUser.setPromoCode(getPromeCode());
            hUser.setReferId(getReferId(promeCode));
            hUser.setDevToken(deviceToken);
            hUser.setSources(source);
            hUser.setAllNum(10);
            hUser.setRemainNum(10);
            hUser.setFreeNum(10);
            hUser.setSources(source);
            hUser.setUserType(1);
            hUser.setTel("");
            hUser.setWhetherBound(false);
            hUser.setSecCode("");
            hUser.setOpenid(UUID.randomUUID().toString());
            hUser.setAccessToken(UUID.randomUUID().toString());
            hUser.setBalance(new BigDecimal(0));
            hUser.setUsername("用户"+(101003+ CommonUtil.getRandomCount(99999)));
        }
        hUserDao.save(hUser);
        return new UserVo(hUser.getId(),hUser.getAccessToken(),hUser.getTel(),hUser.getAllNum(), hUser.getRemainNum(),hUser.getUserType()==2,
                hUser.getVipType(),!hUser.getSecCode().equals(""),hUser.getPromoCode(),new BigDecimal(0),hUserDao.countByReferId(hUser.getId()),
                hUser.getVipDueTime(),hUser.getRemainDown(),hUser.getAllDown());
    }

    //收藏电影
    public Object collectionMovie(CollectionDto collectionDto){
        int uid = tokenService.getUidByToken(collectionDto.getToken());
        HCollection hCollection = hCollectionDao.findByTypeAndMidAndUid(collectionDto.getType(),collectionDto.getMid(),uid);
        if (hCollection !=null){
            throw new BaseException(Meta.HasCollection);
        }
        if (collectionDto.getType() == 3){
            //女优
            hStarDao.findById(collectionDto.getMid()).orElseThrow(()->new BaseException(Meta.StarNOTExist));
        }else {
            HVideo hVideo = hVideoDao.findById(collectionDto.getMid()).orElseThrow(()->new BaseException(Meta.MovieNOTExist));
            if (hVideo.getType()!= collectionDto.getType()){
                //类型不同也不能收藏
                throw new BaseException(Meta.MovieNOTExist);
            }
        }
        hCollection = new HCollection();
        BeanUtils.copyProperties(collectionDto,hCollection);
        hCollection.setUid(uid);
        hCollectionDao.save(hCollection);
        return "";
    }

    //收藏列表
    public Object collectionList(int type,String token){
        int uid = tokenService.getUidByToken(token);
        if (type == 3){
            //女优
            return hCollectionDao.findByTypeAndUid(type,uid).stream().map(item->{
                HStar hStar = hStarDao.findById(item.getMid()).get();
                return new StarItemVo(hStar);
            });
        }else {
            //视频
            return hCollectionDao.findByTypeAndUid(type,uid).stream().map(item->{
                HVideo hVideo = hVideoDao.findById(item.getMid()).get();
                return new VideoItemVo(hVideo);
            });
        }
    }

    //查看所有收藏列表
    public Object collectionListAll(String token){
        int uid = tokenService.getUidByToken(token);
        CollectionAllVo collectionAllVo= new CollectionAllVo();
        collectionAllVo.setStarItemList(hCollectionDao.findByTypeAndUid(3,uid).stream().map(item->{
            HStar hStar = hStarDao.findById(item.getMid()).get();
            return new StarItemVo(hStar);
        }).collect(Collectors.toList()));

        collectionAllVo.setAvItemList(getVideo(1,uid));
        collectionAllVo.setSVideoItemList(getVideo(2,uid));
        return collectionAllVo;
    }

    private List<VideoItemVo> getVideo(int type,int uid){
        return hCollectionDao.findByTypeAndUid(type,uid).stream().map(item->{
            HVideo hVideo = hVideoDao.findById(item.getMid()).get();
            return new VideoItemVo(hVideo);
        }).collect(Collectors.toList());
    }
    //取消收藏
    public Object removeCollection(CollectionDto collectionDto){
        int uid = tokenService.getUidByToken(collectionDto.getToken());
        HCollection hCollection = hCollectionDao.findByTypeAndMidAndUid(collectionDto.getType(),collectionDto.getMid(),uid);
        if (hCollection ==null){
            throw new BaseException(Meta.CollectionNotExist);
        }
        hCollectionDao.delete(hCollection);
        return "";
    }
    //查看用户信息
    public Object getUserInfo(String token){
        HUser hUser = tokenService.getUserInfoByToken(token);
        //hUserDao.countByReferId(hUser.getId()) TODO 优化这里，这里的话推广一个人保存
        return new UserVo(hUser.getId(),hUser.getAccessToken(),hUser.getTel(),hUser.getAllNum(), hUser.getRemainNum(),hUser.getUserType()==2,
                hUser.getVipType(),!hUser.getSecCode().equals(""),hUser.getPromoCode(),new BigDecimal(0),hUserDao.countByReferId(hUser.getId()),
                hUser.getVipDueTime(),hUser.getRemainDown(),hUser.getAllDown());
    }

    //设置安全码
    public Object setSecCode(String token,String code){
        if (code.length() != 6){
            throw new BaseException(Meta.SecCodeNotEnough);
        }
        HUser hUser = tokenService.getUserInfoByToken(token);
        String secCode = hUser.getSecCode();
        if (secCode == null || secCode.equals("")){
            hUser.setSecCode(code);
            tokenService.updateUserInfo(hUser);
        }else {
            throw new BaseException(Meta.SecCodeExist);
        }
        return "";
    }

    //修改安全码
    public Object editSecCode(String token,String oldCode,String newCode){
        if (oldCode.length() != 6 || newCode.length() != 6){
            throw new BaseException(Meta.SecCodeNotEnough);
        }
        HUser hUser = tokenService.getUserInfoByToken(token);
        String secCode = hUser.getSecCode();
        if (secCode.equals(oldCode)){
            hUser.setSecCode(newCode);
            tokenService.updateUserInfo(hUser);
        }else {
            throw new BaseException(Meta.SecOldCodeErr);
        }
        return "";
    }

    //修改安全码
    public Object verifySecCode(String token,String code){
        if (code.length() != 6 ){
            throw new BaseException(Meta.SecCodeNotEnough);
        }
        HUser hUser = tokenService.getUserInfoByToken(token);
        String secCode = hUser.getSecCode();
        if (secCode.equals(code)){
            return "";
        }else {
            throw new BaseException(Meta.SecOldCodeErr);
        }
    }

    //设置mash
    public Object setMash(String token,String code){
        if (code.length()==0){
            throw new BaseException(Meta.MashErr);
        }
        int uid = tokenService.getUidByToken(token);
        String newCode = CommonUtil.filterSpecialCharAndUpper(code);
        if (!newCode.equals(code.toUpperCase())){
            throw new BaseException(Meta.MashFormatErr);
        }
        HMashLog mashLog = hMashDao.findByCodeAndUid(newCode,uid);
        if (mashLog != null){
            throw new BaseException(Meta.MashExist);
        }
        mashLog = new HMashLog();
        mashLog.setCode(newCode);
        mashLog.setUid(uid);
        mashLog.setStatus("未更新");
        mashLog.setCreatedAt(System.currentTimeMillis());
        mashLog.setUpdatedAt(System.currentTimeMillis());
        hMashDao.save(mashLog);
        return "";
    }

    //获取自己的番号求片
    public Object getMash(String token){
        int uid = tokenService.getUidByToken(token);
        return hMashDao.findByUid(uid).stream().map(item->{
            HMashLogVo hMashLogVo = new HMashLogVo();
            hMashLogVo.setCode(item.getCode());
            hMashLogVo.setStatus(item.getStatus());
            hMashLogVo.setNum(hMashDao.countByCode(item.getCode()));
            return hMashLogVo;
        });
    }

    //绑定 解绑 找回 重置安全码
    public Object editUserTel(String token, String tel, String verifyCode,int type){
        HUser hUser;
        if (tel.length()!=11){
            throw new BaseException(Meta.PhoneNumErr);
        }
        switch (type){
            case 1:
                bindTel(token, tel, verifyCode);
                break;
            case 2:
                unbindTel(token, tel, verifyCode);
                break;
            case 3:
                findTel(token, tel, verifyCode);
                break;
            case 4:
                resetSecCode(token, tel, verifyCode);
                break;
            default:
                throw new BaseException(Meta.TypeNOTExist);
        }
        return "";
    }



    private void bindTel(String token, String tel, String verifyCode){
        HUser hUser;
        if (tel.length()!=11){
            throw new BaseException(Meta.PhoneNumErr);
        }
        hUser = tokenService.getUserInfoByToken(token);
        String tel1 = hUser.getTel();
        if (tel1 == null || tel1.equals("")){
            if (verifyCode.equals("123456")){
                if (hUserDao.findByTel(tel) != null){
                    throw new BaseException(Meta.PhoneHasExist);
                }
                //从来没有绑定过就设置一天会员
                if (!hUser.isWhetherBound()){
                    if (hUser.getVipType() == 1){
                        hUser.setVipType(2);
                        hUser.setVipDueTime(LocalDate.now().plusDays(1).atStartOfDay().toEpochSecond(ZoneOffset.of("+8")));
                    }else {
                        hUser.setVipDueTime(hUser.getVipDueTime()+24*60*60);
                    }
                    hUser.setWhetherBound(true);
                }
                hUser.setTel(tel);
                tokenService.updateUserInfo(hUser);
            }else {
                throw new BaseException(Meta.VerifyCodeDue);
            }
        }else {
            throw new BaseException(Meta.PhoneHasExist);
        }
    }

    private void unbindTel(String token, String tel, String verifyCode){
        HUser hUser;
        hUser = tokenService.getUserInfoByToken(token);
        if (!hUser.getTel().equals(tel)){
            throw new BaseException(Meta.PhoneHasEqualErr);
        }
        if (verifyCode.equals("123456")){
            hUser.setTel("");
            tokenService.updateUserInfo(hUser);
        }else {
            throw new BaseException(Meta.VerifyCodeDue);
        }
    }

    private void findTel(String token, String tel, String verifyCode){
        HUser hUser = tokenService.getUserInfoByToken(token);
        if (hUser.getTel().equals(tel)){
            //如果用户的手机号等于原来的手机号 那么
            throw new BaseException(Meta.PhoneHasEqual);
        }
        HUser originalUser;
        if (((originalUser=hUserDao.findByTel(tel)) == null) && hUser.getTel().equals("")){
            //如果没有手机号 那么就是第一次绑定
            bindTel(token, tel, verifyCode);
            return;
        }
        if (((originalUser=hUserDao.findByTel(tel)) == null) && !hUser.getTel().equals("")){
            //如果原来的手机在 就是换号
            if (verifyCode.equals("123456")){
                hUser.setTel(tel);
                tokenService.updateUserInfo(hUser);
            }else {
                throw new BaseException(Meta.VerifyCodeDue);
            }
            return;
        }

        //确定是找回账号
        if (verifyCode.equals("123456")){
            //交换原有两个的账号的信息
            String originDeviceId =  originalUser.getDevToken();

            String nowDeviceId =  hUser.getDevToken();

            originalUser.setDevToken(nowDeviceId);
            originalUser.setAccessToken(UUID.randomUUID().toString());

            hUser.setDevToken(originDeviceId);
            hUser.setAccessToken(UUID.randomUUID().toString());

            tokenService.updateUserInfo(originalUser);
            tokenService.updateUserInfo(hUser);
            throw new BaseException(Meta.TokenExpire);
        }else {
            throw new BaseException(Meta.VerifyCodeDue);
        }
    }
    private void resetSecCode(String token, String tel, String verifyCode){
        HUser hUser = tokenService.getUserInfoByToken(token);
        if (verifyCode.equals("123456")){
            hUser.setSecCode("");
            tokenService.updateUserInfo(hUser);
        }else {
            throw new BaseException(Meta.VerifyCodeDue);
        }
    }


        //上传回馈
    public Object problemFeedback(String token, int type , String detail, HttpServletRequest servletRequest){
        int uid = tokenService.getUidByToken(token);
        try {
            MultipartRequest multipartRequest = (MultipartRequest) servletRequest;
            List<MultipartFile> multipartFiles = multipartRequest.getFiles("img");
            try {
                int i = 0;
                StringBuilder imgPathArr = new StringBuilder();
                for (MultipartFile multipartFile : multipartFiles){
                    String fileName = String.valueOf(System.currentTimeMillis())+(100000+uid)+""+(CommonUtil.getRandomCount(9999)+10000)+".jpg";
                    FileOutputStream fileOutputStream = new FileOutputStream(new File(imgPath,fileName));
                    FileUtil.copy(multipartFile.getInputStream(),fileOutputStream);
                    String imgpath = webPath+"/"+fileName;
                    imgPathArr.append(imgpath).append(",");
                    if (++i >=3){
                        break;
                    }
                }
                if (imgPathArr.length() > 0){
                    imgPathArr.deleteCharAt(imgPathArr.length()-1);
                }
                HFeedBack hFeedBack = new HFeedBack(uid,detail,imgPathArr.toString(),type,1,"",System.currentTimeMillis()/1000,System.currentTimeMillis()/1000);
                hFeedBackDao.save(hFeedBack);
                return "";
            } catch (IOException e) {
                throw new BaseException(Meta.ServerError);
            }
        }catch (Exception e){
            HFeedBack hFeedBack = new HFeedBack(uid,detail,"",type,1,"",System.currentTimeMillis()/1000,System.currentTimeMillis()/1000);
            hFeedBackDao.save(hFeedBack);
        }
        return "";
    }

        //上传回馈
    public Object problemFeedbackBase64(String token, int type , String detail, String img){
        int uid = tokenService.getUidByToken(token);
        try {
            try {
                int i = 0;
                List<byte[]> list = CommonUtil.md5ToByte(img);
                StringBuilder imgPathArr = new StringBuilder();
                for (byte[] b : list){
                    String fileName = String.valueOf(System.currentTimeMillis())+(100000+uid)+""+(CommonUtil.getRandomCount(9999)+10000)+".jpg";
                    FileOutputStream fileOutputStream = new FileOutputStream(new File(imgPath,fileName));
                    FileUtil.copy(b,fileOutputStream);
                    String imgpath = webPath+"/"+fileName;
                    imgPathArr.append(imgpath).append("，");
                    if (++i >=3){
                        break;
                    }
                }
                if (imgPathArr.length() > 0){
                    imgPathArr.deleteCharAt(imgPathArr.length()-1);
                }
                HFeedBack hFeedBack = new HFeedBack(uid,detail,imgPathArr.toString(),type,1,"",System.currentTimeMillis()/1000,System.currentTimeMillis()/1000);
                hFeedBackDao.save(hFeedBack);
                return "";
            } catch (IOException e) {
                throw new BaseException(Meta.ServerError);
            }
        }catch (Exception e){
            HFeedBack hFeedBack = new HFeedBack(uid,detail,"",type,1,"",System.currentTimeMillis()/1000,System.currentTimeMillis()/1000);
            hFeedBackDao.save(hFeedBack);
        }
        return "";
    }

    //获取回馈
    public Object getProblemFeedback(String token){
        int uid = tokenService.getUidByToken(token);
        List<HFeedBack> list = hFeedBackDao.findByUid(uid);
        return list;
    }

    //获取分享链接
    public Object getProblemLinks(String token){
        HUser hUser = tokenService.getUserInfoByToken(token);
        String links = promoteLinkPath+hUser.getPromoCode();
        Map<String,String> map = new HashMap<>();
        map.put("url",links);
        return map;
    }

    private int getAllFreeNum(){
        return 1;
    }

    private int getRemainFreeNum(){
        return 1;
    }


    private String getPromeCode(){
        String promeCode ;
        while (true){
            promeCode = CommonUtil.getItemID(6);
            if (hUserDao.findByPromoCode(promeCode) == null){
                break;
            }
        }
        return promeCode;
    }

    private int getReferId(String promeCode){
        int referId = 0;
        HUser hUser = hUserDao.findByPromoCode(promeCode);
        if (hUser != null){
            return hUser.getId();
        }
        return referId;
    }

}
